#ifndef _DX8_GEN_ATLAS_H_
#define _DX8_GEN_ATLAS_H_

#include "ui/ui_sprite.h"
#include <D3D8.h>

class Dx8Surface;

class DX8GenAtlas
{
public:
	DX8GenAtlas();
	~DX8GenAtlas();

	void				AddSpriteFile(const std::string& Name);
	void				SetupAtlas(int MaxWidth, int MaxHeight, int Depth);
	void				GenerateAtlas(const std::string& BasePath, std::vector<std::string>& List);
	void				SaveAtlas(const std::string& BasePath, std::vector<std::string>& List);
	void				ProcessSingle();
	void				Render();
	void				AddToProcess(const std::string& SpriteName);
	bool				IsDone() { return m_ToProcess.empty(); };
protected:
	struct				AtlasRect
	{
		AtlasRect(int _x, int _y, int _w, int _h) : x(_x), y(_y), w(_w), h(_h) {};
		AtlasRect() : x(0), y(0), w(0), h(0) {};

		bool			CanFit(const AtlasRect&  Rect)
		{
			return w >= Rect.w && h>= Rect.h;
		}
		bool			PerfectFit(const AtlasRect&  Rect)
		{
			return w == Rect.w && h == Rect.h;
		}
		int					w, h;
		int					x, y;
	};
	struct				AtlasEntry
	{
		ui::UISprite		Sprite;
		std::string			Name;
		int					PageIndex;
		AtlasRect			Rect;
		static bool			Sort(const AtlasEntry*& A, const AtlasEntry*& B)
		{
			return (A->Rect.w*A->Rect.h) < (B->Rect.w*B->Rect.h);
		}
	};
	struct				AtlasNode
	{
		AtlasNode() : pEntry(0) { NodeA[0]=NodeA[1]=NULL; };
		AtlasNode*		NodeA[2];	// we're basically a specialized binary tree
		AtlasRect		Rect;
		AtlasEntry*		pEntry;
		AtlasNode*		Insert(AtlasEntry* pEntry);
		void			Render(const math::Vec2& TL, const math::Vec2& Size);
		AtlasNode*		GetNodeByPos(const math::Vec2& P, const math::Vec2& TL, const math::Vec2& Size);
		void			UpdateFile(int	PageIndex);
	};
	struct				AtlasPage
	{
		AtlasPage() :
			pTexture(NULL)
		{

		};
		AtlasNode					Root;
		LPDIRECT3DTEXTURE8			pTexture;
		bool						AddEntry(AtlasEntry* pEntry);
		void						Save(const std::string& Name);
	};
	static void						OutputAtlasElement(AtlasEntry* pEntry, void* pData);
	AtlasPage*						AddEntry(AtlasEntry* pEntry);

	int								m_AtlasW, m_AtlasH, m_AtlasD;
	std::vector<AtlasEntry*>		m_ToProcess;
	std::vector<AtlasEntry*>		m_ToPassThrough;
	std::vector<AtlasPage*>			m_Pages;
	num::NamedSet<AtlasEntry*>		m_Added;
	
};

#endif //